/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jobscheduling.model;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import jobscheduling.algorithms.bee.BeeScheduler;
import jobscheduling.algorithms.glowworm.GlowwormScheduler;
import jobscheduling.algorithms.pso.PSOScheduler;
import jobscheduling.gui.ComputingPanel;
import jobscheduling.gui.GUI;

/**
 *
 * @author Dawid
 */
public class Computation extends Thread implements Serializable {
    protected Problem _problem;
    protected List<Solution> _results;
    protected List<Thread> _threads;
    protected Map<String, String> _bees;
    protected Map<String, String> _pso;
    protected Map<String, String> _glowworm;
    protected ComputingPanel _cp;
    
    public Computation (Problem problem, Map<String, String> bees,
                        Map<String, String> pso, Map<String, String>glow,
                        ComputingPanel cp){
        _problem = problem;
        _bees = bees;
        _pso = pso;
        _glowworm = glow;
        _results = new LinkedList<Solution>();
        _threads = new LinkedList<Thread>();
        _cp = cp;
    }
    
    public synchronized void update (String algorithm, int[] permutation, int totalTime){
        _cp.nextIteration(algorithm, totalTime);
    }
    
    @Override
    public void run (){
        if (_bees != null){
            Solution result = new Solution(GUI.BEES, _bees, _problem, this);
            Thread thread = new BeeScheduler(_problem.getRawJobs(), result, _bees);
            _results.add(result);
            _threads.add(thread);
            thread.start();
        }
        if (_pso != null){
            Solution result = new Solution(GUI.PSO, _pso, _problem, this);
            Thread thread = new PSOScheduler(_problem.getRawJobs(), result, _pso);
            _results.add(result);
            _threads.add(thread);
            thread.start();
        }
        if (_glowworm != null){
            Solution result = new Solution( GUI.GW, _glowworm, _problem, this);
            Thread thread = new GlowwormScheduler(_problem.getRawJobs(), result, _glowworm);
            _results.add(result);
            _threads.add(thread);
            thread.start();
        }
        boolean someAlive = true;
        boolean isBeeFinished = false;
        boolean isPsoFinished = false;
        boolean isWormFinished = false;
        while (someAlive){
            Iterator<Thread> iterator = _threads.iterator();
            if (iterator.hasNext() == false){
                break;
            }
            someAlive = false;
            while (iterator.hasNext()){
                Thread next = iterator.next();
                if (next.isAlive() == true){
                    someAlive = true;
                } else {
                    if (next instanceof BeeScheduler && !isBeeFinished){
                        _cp.finish(GUI.BEES);
                        isBeeFinished = true;
                    } else if (next instanceof GlowwormScheduler && !isWormFinished){
                        _cp.finish(GUI.GW);
                        isWormFinished = true;
                    } else if (next instanceof PSOScheduler && !isPsoFinished){
                        _cp.finish(GUI.PSO);
                        isPsoFinished = true;
                    }
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Computation.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        Output.getInstance().addSolutions(_results);
    }
}
